package conson.tech.manage.coupons.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import conson.tech.core.exception.BaseException;
import conson.tech.core.response.Response;
import conson.tech.manage.common.constant.BusinessMessage;
import conson.tech.manage.coupons.entity.dto.*;
import conson.tech.manage.coupons.entity.pojo.*;
import conson.tech.manage.coupons.entity.vo.*;
import conson.tech.manage.coupons.mapper.*;
import conson.tech.manage.coupons.service.CouponsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * ClassName: CouponsServiceImpl
 * Description:
 * Author: ZYF
 * Date: 2020/7/21
 * Version: 1.0
 */
@Slf4j
@Service
public class CouponsServiceImpl implements CouponsService {

    @Autowired
    private CouponsBatchMapper couponsBatchMapper;

    @Autowired
    private CouponsCostProviderMapper couponsCostProviderMapper;

    @Autowired
    private OperationLogMapper operationLogMapper;

    @Autowired
    private CouponsUsingRangeMapper couponsUsingRangeMapper;


    @Autowired
    private MerchantInformationMapper merchantInformationMapper;

    /**
     *  新增优惠券
     *  zyf
     *  2020/07/21
     * @param dto 新增优惠券入参
     * @param userId 用户id
     * @param userName 用户名称
     */
    @Override
    @Transactional
    public Response addCoupons(CouponsDto dto, Long userId,String userName){

        try{
            log.info("开始新增优惠券信息");

            //新增优惠券信息表
            CouponsBatch couponsBatch = new CouponsBatch();
            couponsBatch.setProvider(dto.getProvider());
            couponsBatch.setProvidedType(dto.getProvidedType());
            couponsBatch.setBatchName(dto.getBatchName());
            couponsBatch.setBatchType(dto.getBatchType());
            couponsBatch.setBatchMoney(dto.getBatchMoney());
            couponsBatch.setLimitMoney(dto.getLimitMoney());
            couponsBatch.setOnlineFlag(dto.getOnlineFlag());
            couponsBatch.setOfflineFlag(dto.getOfflineFlag());
            couponsBatch.setShowTitle(dto.getShowTitle());
            couponsBatch.setUsedDes(dto.getUsedDes());
            couponsBatch.setTimeLimit(dto.getTimeLimit());
            couponsBatch.setStartTime(dto.getStartTime());
            couponsBatch.setEndTime(dto.getEndTime());
            couponsBatch.setRelativeTime(dto.getRelativeTime());
            couponsBatch.setApplicateNum(dto.getApplicateNum());
            couponsBatch.setStockNum(dto.getApplicateNum());
            couponsBatch.setLimitNum(dto.getLimitNum());
            couponsBatch.setWarningNum(dto.getWarningNum());
            couponsBatch.setExpirationNotice(dto.getExpirationNotice());
            couponsBatch.setSmsFlag(dto.getSmsFlag());
            couponsBatch.setSmsDes(dto.getSmsDes());
            couponsBatch.setPushFlag(dto.getPushFlag());
            couponsBatch.setState(0);
            couponsBatch.setDeleteFlag(1);
            couponsBatch.setCreateBy(userId);
            couponsBatch.setCreateTime(LocalDateTime.now());
            couponsBatch.setApplyName(dto.getApplyName());
            couponsBatch.setRangeType(dto.getRangeType());
            this.couponsBatchMapper.insert(couponsBatch);

            long couponsId = couponsBatch.getId();

            //存储优惠券费用归属信息
            for(int i = 0;i<dto.getCouponsCostDtos().size();i++){
                CouponsCostProvider couponsCostProvider = new CouponsCostProvider();
                couponsCostProvider.setBatchId(couponsId);
                couponsCostProvider.setType(dto.getCouponsCostDtos().get(i).getType());
                couponsCostProvider.setCostRatio(dto.getCouponsCostDtos().get(i).getCostRatio());
                //couponsCostProvider.setProviderCode(); 一期冗余字段，后期费用归属方有修正，此处需要同步处理
                this.couponsCostProviderMapper.insert(couponsCostProvider);
            }

            //存储优惠券使用范围表
            for(int j = 0; j<dto.getCouponsUsingRangeDtos().size();j++){

                CouponsUsingRange range = new CouponsUsingRange();
                range.setBatchId(couponsId);
                range.setRemark("");
                range.setUsingId(Long.parseLong(dto.getCouponsUsingRangeDtos().get(j).getUsingId()));
                range.setShopLimit(dto.getCouponsUsingRangeDtos().get(j).getShopLimit());
                this.couponsUsingRangeMapper.insert(range);

            }

            //优惠券新增完成之后，录入优惠券操作日志表
            OperationLogDto opera = new OperationLogDto();
            opera.setCreateBy(userName);
            opera.setDomainId(couponsId);
            opera.setOperateDesc("创建优惠券");
            this.editLog(opera);
            log.info("优惠券新增成功");
            return  Response.success();
        }catch (Exception e){
            log.error("新增优惠券失败，请重新确认录入信息",e);
            return Response.fail("新增优惠券失败，请稍后重试");
        }
    }


    /**
     * 优惠券作废
     * zyf
     * 2020/07/21
     * @param couponsId 优惠券批次id
     * @param userId 用户id
     * @param userName 用户名称
     */
    @Override
    @Transactional
    public Response delCoupons(Long couponsId,Long userId,String userName) {

        try {
            //先判断该优惠券批次是否存在
            CouponsBatch couponsBatch = this.couponsBatchMapper.selectById(couponsId);
            if (couponsBatch.getDeleteFlag() != 1) {
                log.info("优惠券[{}]已删除，请重新确认", couponsId);
                return Response.fail("优惠券已删除，请重新确认");
            }
            couponsBatch.setState(6);
            couponsBatch.setUpdateBy(userId);
            couponsBatch.setUpdateTime(LocalDateTime.now());
            this.couponsBatchMapper.updateById(couponsBatch);

            //优惠券作废，录入优惠券操作日志表
            OperationLogDto opera = new OperationLogDto();
            opera.setCreateBy(userName);
            opera.setDomainId(couponsId);
            opera.setOperateDesc("作废");
            this.editLog(opera);
            return  Response.success();
        } catch (Exception e) {
            log.error("优惠券作废失败",e);
            return Response.fail("优惠券作废失败，请联系管理员查看原因");
        }
    }


    /**
     * 修改优惠券信息
     * zyf
     * 2020/07/21
     * @param dto 优惠券修改入参
     * @param userId 用户id
     * @param couponsId 优惠券批次id
     * @param userName 用户名称
     */
    @Override
    @Transactional
    public  Response editCoupons(CouponsDto dto,Long userId,Long couponsId,String userName){

        try {

            log.info("修改优惠券信息");

            //查询优惠券信息
            CouponsBatch batch = this.couponsBatchMapper.selectById(couponsId);
            //修改优惠券信息
            BeanUtil.copyProperties(dto,batch);
            batch.setUpdateBy(userId);
            batch.setUpdateTime(LocalDateTime.now());
            //若优惠券的状态为待财务审核、待运营审核、审核驳回
            if(batch.getState() ==1 || batch.getState() == 2|| batch.getState() == 4){
                batch.setState(0);
            }
            this.couponsBatchMapper.updateById(batch);

            //审核状态为审核通过的优惠券，修改时不允许修改费用归属以及商户范围
            if(batch.getState() != 3){
                //修改优惠券费用归属
                /**
                 *  修改优惠券费用归属分为3种情况
                 *  1、只修改优惠券费用归属比例
                 *  2、新增优惠券费用类型
                 *  3、删除优惠券费用类型
                 */
                //删除之前的优惠券费用类型
                this.couponsCostProviderMapper.deleteCost(couponsId);
                //将修改之后的存储到数据库中
                for(int i =0 ;i<dto.getCouponsCostDtos().size();i++){

                    CouponsCostProvider provider = new CouponsCostProvider();
                    provider.setBatchId(couponsId);
                    provider.setCostRatio(dto.getCouponsCostDtos().get(i).getCostRatio());
                    provider.setType(dto.getCouponsCostDtos().get(i).getType());
                    //provider.setProviderCode();  一期冗余字段
                    this.couponsCostProviderMapper.insert(provider);

                }

                //删除之前的商品费用范
                //存储优惠券使用范围表
                this.couponsUsingRangeMapper.deleteRange(couponsId);
                if (dto.getCouponsUsingRangeDtos()!= null){
                    for(int j = 0; j<dto.getCouponsUsingRangeDtos().size();j++){

                        CouponsUsingRange range = new CouponsUsingRange();
                        range.setBatchId(couponsId);
                        range.setRemark("");
                        range.setUsingId(Long.parseLong(dto.getCouponsUsingRangeDtos().get(j).getUsingId()));
                        range.setShopLimit(dto.getCouponsUsingRangeDtos().get(j).getShopLimit());
                        this.couponsUsingRangeMapper.insert(range);

                    }

                }
            }

            //优惠券修改完成之后，录入优惠券操作日志表
            OperationLogDto opera = new OperationLogDto();
            opera.setCreateBy(userName);
            opera.setDomainId(couponsId);
            opera.setOperateDesc("修改优惠券");
            this.editLog(opera);

            log.info("优惠券信息修改完成");
            return Response.success();
        }catch (Exception e){

            log.error("优惠券信息修改失败",e);
            return Response.fail("优惠券信息修改失败,请联系管理员处理");

        }
    }

    /**
     * 查询优惠券列表信息
     * zyf
     * 2020/7/21
     * @param pageSize 页宽
     * @param pageIndex 页号
     * @param dto 查询条件
     */
    @Override
    public Page<CouponsBatchVo> searchCouponsList(Integer pageSize, Integer pageIndex, CouponsSearchDto dto){
        try{
            log.info("开始查询优惠券列表信息");
            //构建分页查询条件
            Page<CouponsBatchVo> page = new Page<>(pageIndex,pageSize);

            page = this.couponsBatchMapper.searchCouponsList(page,dto);

            log.info("结束查询优惠券列表信息");
            return page;
        }catch (Exception e){
            log.error("查询优惠券列表信息失败",e);
            throw new BaseException(BusinessMessage.COUPONS_LIST_ERROR);
        }
    }

    /**
     * 查询优惠券详细信息
     * zyf
     * 2020/07/22
     * @param couponsId 优惠券批次id
     */
    @Override
    public CouponsDetailVo detailCoupons(Long couponsId){

        try {

            log.info("根据优惠券批次id[{}]，查询优惠券详细信息",couponsId);

            CouponsDetailVo couponsDetailVo = this.couponsBatchMapper.detailCoupons(couponsId);

            CouponsUsingRange usingRange = this.couponsUsingRangeMapper.selectOne(new QueryWrapper<CouponsUsingRange>().eq("batch_id", couponsId));

            couponsDetailVo.setUsingId(usingRange.getUsingId());

            log.info("查询优惠券[{}]，完成");
            return couponsDetailVo;

        }catch (Exception e){
            log.error("查询优惠券详细信息失败",e);
            throw new BaseException(BusinessMessage.COUPONS_DETAIL_ERROR);
        }
    }

    /**
     * 单优惠券审核(创建)
     * zyf
     * 2020/07/22]
     * @param  userId 用户id
     * @param couponsId 优惠券批次id
     */
    @Override
    @Transactional
    public Response auditCoupon(Long couponsId,Long userId,String userName){

        try{
            log.info("开始对优惠券进行审核");

            //根据优惠券id查询优惠券信息
            CouponsBatch batch = this.couponsBatchMapper.selectById(couponsId);
            //判断优惠券是否已经被其他人员操作
            if(batch.getState() != 0 ){
                throw  new BaseException(BusinessMessage.COUPONS_STATE_ERROR);
            }

            //修改优惠券状态
            batch.setState(1);
            batch.setUpdateTime(LocalDateTime.now());
            batch.setUpdateBy(userId);
            this.couponsBatchMapper.updateById(batch);

            //优惠券提审完成之后，录入优惠券操作日志表
            OperationLogDto opera = new OperationLogDto();
            opera.setCreateBy(userName);
            opera.setDomainId(couponsId);
            opera.setOperateDesc("提交审核");
            this.editLog(opera);
            log.info("优惠券[{}]，状态变更为待运营管理审核",couponsId);
            return  Response.success();

        }catch (Exception e){
            log.error("优惠券审核失败",e);
            throw  new BaseException(BusinessMessage.COUPONS_AUDIT_ERROR);
        }
    }


    /**
     *  优惠券批量审核
     *  zyf
     *  2020/07/22
     * @param couponsIds 优惠券批次id集合
     * @param userId 用户id
     * @param userName 用户名称
     */
    @Override
    @Transactional
    public  Response auditListCoupon(List<Long> couponsIds, Long userId,String userName){


            log.info("开始批量提审优惠券");

            //校验优惠券是否已经被操作过
            for (int i = 0;i<couponsIds.size();i++){
                //通过批次id查询优惠券信息
                CouponsBatch batch = this.couponsBatchMapper.selectById(couponsIds.get(i));

                //判断优惠券状态是否为初始
                if (batch.getState() != 0) {
                    throw new BaseException(BusinessMessage.COUPONS_STATE_ERROR);
                }
                //修改优惠券状态
                batch.setState(1);
                batch.setUpdateTime(LocalDateTime.now());
                batch.setUpdateBy(userId);
                this.couponsBatchMapper.updateById(batch);

                //优惠券新增完成之后，录入优惠券操作日志表
                OperationLogDto opera = new OperationLogDto();
                opera.setCreateBy(userName);
                opera.setDomainId(couponsIds.get(i));
                opera.setOperateDesc("提交审核");
                this.editLog(opera);
            }
            log.info("优惠券批量提审成功");
            return  Response.success();
    }

    /**
     *  优惠券复制新增
     *  zyf
     *  2020/07/22
     * @param couponsId 优惠券批次id
     * @param userId 用户id
     * @param userName 用户名称
     */
    @Override
    @Transactional
    public CouponsDetailVo copyCoupons(Long couponsId,Long userId,String userName){

        try{

            log.info("开始复制新增优惠券");

            //通过优惠券批次id，查询优惠券信息
            CouponsCopyVo couponsCopyVo = this.couponsBatchMapper.queryCouponsInformation(couponsId);
            CouponsBatch batch = new CouponsBatch();
            BeanUtil.copyProperties(couponsCopyVo,batch);
            batch.setApplyName(userName);
            batch.setCreateTime(LocalDateTime.now());
            batch.setCreateBy(userId);
            batch.setStockNum(couponsCopyVo.getApplicateNum());
            this.couponsBatchMapper.insert(batch);
            Long id = batch.getId();

            //根据优惠券批次id，查询优惠券费用占比
            List<CouponsCostProvider> couponsCostProviders = this.couponsCostProviderMapper.queryCostProvider(couponsId);
            for(int i = 0;i<couponsCostProviders.size();i++){
                CouponsCostProvider  couponsCostProvider = new CouponsCostProvider();
                couponsCostProvider.setProviderCode(couponsCostProviders.get(i).getProviderCode());
                couponsCostProvider.setType(couponsCostProviders.get(i).getType());
                couponsCostProvider.setCostRatio(couponsCostProviders.get(i).getCostRatio());
                couponsCostProvider.setBatchId(id);
                this.couponsCostProviderMapper.insert(couponsCostProvider);
            }
            CouponsUsingRange usingRange = this.couponsUsingRangeMapper.selectOne(new QueryWrapper<CouponsUsingRange>().eq("batch_id", couponsId));
            CouponsUsingRange couponsUsingRange = new CouponsUsingRange();
            couponsUsingRange.setBatchId(id);
            couponsUsingRange.setRemark(usingRange.getRemark());
            couponsUsingRange.setShopLimit(usingRange.getShopLimit());
            couponsUsingRange.setUsingId(usingRange.getUsingId());

            this.couponsUsingRangeMapper.insert(couponsUsingRange);


            //优惠券新增完成之后，录入优惠券操作日志表
            OperationLogDto opera = new OperationLogDto();
            opera.setCreateBy(userName);
            opera.setDomainId(id);
            opera.setOperateDesc("创建优惠券");
            this.editLog(opera);

            log.info("新增复制优惠券完成");
            return this.couponsBatchMapper.detailCoupons(id);

        }catch (Exception e){
            log.error("复制优惠券出错",e);
            throw new BaseException(BusinessMessage.COUPONS_COPY_ERROR);
        }
    }

    /**
     * 通用日志写入方法
     * zyf
     * 2020/07/22
     * @param dto 日志入参
     */
    private Response editLog(OperationLogDto dto){
        try{
            log.info("开始写入日志操作表");
            OperationLog operationLog = new OperationLog();
            operationLog.setType(1);
            operationLog.setCreateBy(dto.getCreateBy());
            operationLog.setCreateTime(LocalDateTime.now());
            operationLog.setDomainId(dto.getDomainId());
            operationLog.setOperateDesc(dto.getOperateDesc());
            operationLog.setOperateType(0);
            operationLog.setRemark(dto.getRemark());
            this.operationLogMapper.insert(operationLog);
            log.info("日志操作表填写完成");
            return Response.success();
        }catch (Exception e){
            log.error("写入日志操作表失败",e);
            throw new BaseException(BusinessMessage.OPERATION_LOG_WRITE_ERROR);
        }
    }

    /**
     * 查询优惠券操作日志信息
     * zyf
     * 2020/7/22
     * @param couponsId 优惠券批次
     */
    @Override
    public List<OperationLogVo> queryOperationLog(Long couponsId){

        try{

            log.info("开始查询优惠券批次日志信息");

            List<OperationLogVo> operationLogVos = this.operationLogMapper.queryOperationLog(couponsId);

            log.info("查询优惠券批次日志信息完成");

            return operationLogVos;

        }catch (Exception e){
            log.error("查询优惠券操作日志列表失败",e);
            throw new BaseException(BusinessMessage.OPERATION_LOG_QUERY_ERROR);
        }
    }

    /**
     * 运营管理员单次审核优惠券
     * zyf
     * 2020/7/22
     * @param couponsId 优惠券批次id
     * @param dto 运营管理员审核入参
     * @param userId 用户id
     * @param  userName  用户名称
     */
    @Override
    @Transactional
    public  Response auditCoupons(Long couponsId, CouponsAuditDto dto, Long userId,String userName){

        try{
            log.info("运营管理员审核优惠券开始");

            CouponsBatch batch = this.couponsBatchMapper.selectById(couponsId);
            if(batch.getState()!= 1){
                throw new BaseException(BusinessMessage.COUPONS_STATE_ERROR);
            }
            batch.setCreateBy(userId);
            batch.setCreateTime(LocalDateTime.now());
            if(dto.getAuditState() == 1){
                batch.setState(2);
            }else{
                batch.setState(4);
            }
            this.couponsBatchMapper.updateById(batch);

            //插入日志信息
            OperationLog operationLog = new OperationLog();
            operationLog.setRemark(dto.getRemark());
            operationLog.setType(1);
            operationLog.setDomainId(couponsId);
            operationLog.setOperateType(0);
            operationLog.setCreateBy(userName);
            operationLog.setCreateTime(LocalDateTime.now());
            if(dto.getAuditState() == 1){
                operationLog.setOperateDesc("运营审核通过");
            }else {
                operationLog.setOperateDesc("运营审核拒绝");
            }
            this.operationLogMapper.insert(operationLog);

            log.info("运营管理员审核优惠券结束");

            return  Response.success();
        }catch (Exception e){
            log.error("运营审核优惠券失败",e);
            throw new BaseException(BusinessMessage.COUPONS_AUDIT_ERROR);
        }
    }

    /**
     * 运营管理批量审核优惠券
     * zyf
     * 2020/07/23
     * @param dto 优惠券审核入参
     * @param userId 用户id
     * @param userName 用户名称
     */
    @Override
    @Transactional
    public Response auditListCoupons(CouponsAuditListDto dto, Long userId, String userName){

            log.info("运营管理员开始批量审核优惠券");

            for(int i = 0; i <dto.getCouponsIds().size();i++){

                //根据优惠券id，获取优惠券信息
                CouponsBatch batch = this.couponsBatchMapper.selectById(dto.getCouponsIds().get(i));
                if(batch.getState() != 1){
                    throw new BaseException(BusinessMessage.COUPONS_STATE_ERROR);
                }
                if(dto.getAuditState() == 1){
                    batch.setState(2);
                }else{
                    batch.setState(4);
                }
                batch.setCreateBy(userId);
                batch.setCreateTime(LocalDateTime.now());

                this.couponsBatchMapper.updateById(batch);

                //插入日志信息
                OperationLog operationLog = new OperationLog();
                operationLog.setRemark(dto.getRemark());
                operationLog.setType(1);
                operationLog.setDomainId(dto.getCouponsIds().get(i));
                operationLog.setOperateType(0);
                operationLog.setCreateBy(userName);
                operationLog.setCreateTime(LocalDateTime.now());
                if(dto.getAuditState() == 1){
                    operationLog.setOperateDesc("运营审核通过");
                }else {
                    operationLog.setOperateDesc("运营审核拒绝");
                }
                this.operationLogMapper.insert(operationLog);
            }
            log.info("运营管理员批量审核优惠券完成");
            return Response.success();
    }

    /**
     * 财务管理员单次审核优惠券
     * zyf
     * 2020/7/22
     * @param couponsId 优惠券批次id
     */
    @Override
    @Transactional
    public  Response auditFinanceCoupons(Long couponsId, CouponsAuditDto dto, Long userId,String userName){

            log.info("财务管理员审核优惠券开始");

            CouponsBatch batch = this.couponsBatchMapper.selectById(couponsId);
            if(batch.getState()!= 2){
                throw new BaseException(BusinessMessage.COUPONS_STATE_ERROR);
            }
            if(dto.getAuditState() == 1){
                batch.setState(3);
            }else {
                batch.setState(4);
            }
            batch.setCreateBy(userId);
            batch.setCreateTime(LocalDateTime.now());


            this.couponsBatchMapper.updateById(batch);

            //插入日志信息
            OperationLog operationLog = new OperationLog();
            operationLog.setRemark(dto.getRemark());
            operationLog.setType(1);
            operationLog.setDomainId(couponsId);
            operationLog.setOperateType(0);
            operationLog.setCreateBy(userName);
            operationLog.setCreateTime(LocalDateTime.now());
            if(dto.getAuditState() == 1){
                operationLog.setOperateDesc("财务审核通过");
            }else {
                operationLog.setOperateDesc("财务审核拒绝");
            }
            this.operationLogMapper.insert(operationLog);

            log.info("财务审核优惠券结束");

            return  Response.success();
    }

    /**
     * 财务管理批量审核优惠券
     * zyf
     * 2020/07/23
     * @param dto 财务批量审核入参
     * @param userId 用户id
     * @param userName 用户名称
     */
    @Override
    @Transactional
    public Response auditFinanceListCoupons(CouponsAuditListDto dto,Long userId,String userName){

            log.info("财务开始批量审核优惠券");

            for(int i = 0; i <dto.getCouponsIds().size();i++){

                //根据优惠券id，获取优惠券信息
                CouponsBatch batch = this.couponsBatchMapper.selectById(dto.getCouponsIds().get(i));
                if(batch.getState() != 2){
                    throw new BaseException(BusinessMessage.COUPONS_STATE_ERROR);
                }
                if(dto.getAuditState() == 1){
                    batch.setState(3);
                }else {
                    batch.setState(4);
                }
                batch.setCreateBy(userId);
                batch.setCreateTime(LocalDateTime.now());

                this.couponsBatchMapper.updateById(batch);

                //插入日志信息
                OperationLog operationLog = new OperationLog();
                operationLog.setRemark(dto.getRemark());
                operationLog.setType(1);
                operationLog.setDomainId(dto.getCouponsIds().get(i));
                operationLog.setOperateType(0);
                operationLog.setCreateBy(userName);
                operationLog.setCreateTime(LocalDateTime.now());
                if(dto.getAuditState() == 1){
                    operationLog.setOperateDesc("财务审核通过");
                }else {
                    operationLog.setOperateDesc("财务审核拒绝");
                }
                this.operationLogMapper.insert(operationLog);
            }
            log.info("财务批量审核优惠券完成");
            return Response.success();

    }

    /**
     * 查询商家列表
     */
    @Override
     public List<MerchantInformationVo> queryMerchant(){

        return this.merchantInformationMapper.queryMerchant();
     }


}
